package io.gitee.mayan50.autoassociate.aop;

import com.baomidou.mybatisplus.core.metadata.IPage;
import io.gitee.mayan50.autoassociate.annotation.AutoAssociate;
import io.gitee.mayan50.autoassociate.auto.AutoAssociateManager;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Collection;
import java.util.List;

import static io.gitee.mayan50.autoassociate.constant.AutoAssociateConstant.BASE_AUTO;
import static io.gitee.mayan50.autoassociate.constant.AutoAssociateConstant.USER_AUTO;

/**
 * 关联关系Aop
 */
@Aspect
public class AutoAssociateAop {

    @Pointcut("execution(* com.baomidou.mybatisplus.extension.service.IService.*(..))")
    public void pointCut() {}

    @Autowired
    private AutoAssociateManager autoAssociateManager;

    @Around("pointCut()")
    public Object pointCutAfter(ProceedingJoinPoint joinPoint) {
        return getObject(joinPoint, BASE_AUTO);
    }

    @Pointcut("@annotation(io.gitee.mayan50.autoassociate.annotation.AutoAssociate)")
    public void autoAssociate() {}

    @Around("autoAssociate()")
    public Object autoAssociateAfter(ProceedingJoinPoint joinPoint) {
        return getObject(joinPoint, USER_AUTO);
    }

    public String getCollectionClass(Object obj) {
        Collection<?> collection = (Collection<?>) obj;
        if(collection == null || collection.isEmpty()) return null;
        Object entity = collection.iterator().next();
        return entity.getClass().getName();
    }

    private Object getObject(ProceedingJoinPoint joinPoint, int autoType) {
        try {
            Object obj = joinPoint.proceed();
            AutoAssociate autoAssociate = joinPoint.getTarget().getClass().getAnnotation(AutoAssociate.class);
            if (obj == null || autoAssociateManager == null || (autoType == BASE_AUTO && !autoAssociateManager.isBaseEnable())) return obj;
            Object target = obj;
            if (obj instanceof IPage) target = ((IPage<?>) obj).getRecords();
            String className = target.getClass().getName();
            if(target instanceof Collection) className = getCollectionClass(target);
            if (autoAssociateManager.isEntity(className)) autoAssociateManager.autoAssociateObj(target, autoAssociate);
            return obj;
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return null;
    }

}
